package com.hee.erp.aop;

import com.hee.erp.filter.LoginContextHolder;
import com.hee.erp.modules.entity.SysUser;
import com.hee.erp.pojo.LoginInfo;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.List;

//@Aspect
//@Component
public class SetCommonFieldsAspect {

    /**
     * 在插入数据之前，设置createTime,modifyTime
     *
     * @param joinPoint
     * @throws Exception
     */
    @Before("execution(* com.baomidou.mybatisplus.extension.service..*.saveBatch(..))")
    public void setCreateAndUpdateInfoBeforeSave(JoinPoint joinPoint) throws Exception {
        System.out.println(joinPoint.getSignature());
        setCreateInfos(joinPoint);
    }

    @Before("execution(* com.baomidou.mybatisplus.extension.service..*.saveOrUpdateBatch(..))")
    public void setCreateAndUpdateInfoBeforeSaveOrUpdateBatch(JoinPoint joinPoint) throws Exception {
        System.out.println(joinPoint.getSignature());
        setCreateInfos(joinPoint);
    }

    @Before("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.insert(..))")
    public void setCreateAndUpdateInfoBeforeInsert(JoinPoint joinPoint) throws Exception {
        System.out.println(joinPoint.getSignature());
        LoginInfo loginInfo = LoginContextHolder.get();
        Object[] args = joinPoint.getArgs();

        for (Object obj : args) {
            Class<?> clazz = obj.getClass();

            setCreateInfo(loginInfo, obj, clazz);

            setModifyInfo(loginInfo, obj, clazz);

            if (obj instanceof SysUser) {
                Field dbKey = clazz.getDeclaredField("dbKey");
                if (dbKey != null) {
                    dbKey.setAccessible(true);
                    dbKey.set(obj, loginInfo.getUserDbKey());
                }
            }
        }
    }

    /**
     * 在修改数据之前，设置modifyTime
     *
     * @param joinPoint
     * @throws Exception
     */
    @Before("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update*(..))")
    public void setModifyInfoBeforeUpdate(JoinPoint joinPoint) throws Exception {
        System.out.println(joinPoint.getSignature());
        LoginInfo loginInfo = LoginContextHolder.get();
        Object[] args = joinPoint.getArgs();
        for (Object obj : args) {
            Class<?> clazz = obj.getClass();
            setModifyInfo(loginInfo, obj, clazz);
        }
    }

    private void setCreateInfos(JoinPoint joinPoint) throws NoSuchFieldException, IllegalAccessException {
        LoginInfo loginInfo = LoginContextHolder.get();
        Object[] args = joinPoint.getArgs();

        for (Object arg : args) {
            for (Object obj : (List) arg) {
                Class<?> clazz = obj.getClass();

                setCreateInfo(loginInfo, obj, clazz);

                setModifyInfo(loginInfo, obj, clazz);

                if (obj instanceof SysUser) {
                    Field dbKey = clazz.getDeclaredField("dbKey");
                    if (dbKey != null) {
                        dbKey.setAccessible(true);
                        dbKey.set(obj, loginInfo.getUserDbKey());
                    }
                }
            }
        }
    }

    private void setCreateInfo(LoginInfo loginInfo, Object obj, Class<?> clazz) throws NoSuchFieldException, IllegalAccessException {
        Field createTime = clazz.getDeclaredField("createTime");
        if (createTime != null) {
            createTime.setAccessible(true);
            createTime.set(obj, LocalDateTime.now());
        }

        Field createUser = clazz.getDeclaredField("createUser");
        if (createUser != null) {
            createUser.setAccessible(true);
            createUser.set(obj, loginInfo.getUserId());
        }

        try {
            Field delFlag = clazz.getDeclaredField("delFlag");
            if (delFlag != null) {
                delFlag.setAccessible(true);
                delFlag.set(obj, false);
            }
        }catch (Exception e){

        }
    }

    private void setModifyInfo(LoginInfo loginInfo, Object obj, Class<?> clazz) throws NoSuchFieldException, IllegalAccessException {
        try {
            Field modifyTime = clazz.getDeclaredField("modifyTime");
            if (modifyTime != null) {
                modifyTime.setAccessible(true);
                modifyTime.set(obj, LocalDateTime.now());
            }

            Field modifyUser = clazz.getDeclaredField("modifyUser");
            if (modifyUser != null) {
                modifyUser.setAccessible(true);
                modifyUser.set(obj, loginInfo.getUserId());
            }
        }catch(Exception e){}
    }

}
